package com.yonyou.pmclouds.outter.tenantsdk.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.iuap.tenant.entity.UserSource;
import com.yonyou.iuap.tenant.sdk.UserCenter;
import com.yonyou.iuap.tenant.utils.TenantSdkPropertyUtil;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.CommonProgramConsts;
import com.yonyou.pmclouds.outter.tenantsdk.entity.TenantSdkResultInfo;
import com.yonyou.pmclouds.outter.tenantsdk.entity.TenantSdkUserInfo;
import com.yonyou.pmclouds.outter.tenantsdk.rmiitf.IUserInfoService;
import com.yonyou.pmclouds.outter.util.YhtSdkServerProperties;
import com.yonyou.pmclouds.user.entity.UserInfo;
import com.yonyou.pmclouds.user.entity.UserSearchResultVO;
import com.yonyou.pmclouds.user.entity.UserSingleQueryVO;
import com.yonyou.yht.sdkutils.sign.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.util.*;

/**
 * @Description: iuap-tenant-sdk 信息服务类
 * @Author: zhangzhonghao
 * @Date: 2020-04-16
 */

@Slf4j
@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = IUserInfoService.class)
public class UserInfoServiceImpl implements IUserInfoService {

    public static ObjectMapper objectMapper;

    private static String baseUrl = TenantSdkPropertyUtil.getPropertyByKey("apps.tenant.base.url");

    static {
        objectMapper = new ObjectMapper();
        //忽略未识别字段
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 批量添加用户，如果存在的用户直接添加关联关系
     *
     * @param userInfoArray 用户信息
     * @return 成功后返回的用户信息
     */
    @Override
    public TenantSdkUserInfo[] addUsersAndRelations(TenantSdkUserInfo[] userInfoArray) throws BusinessException {
        if (userInfoArray == null || userInfoArray.length <= 0) {
            return null;
        }

        List<TenantSdkUserInfo> result = new ArrayList<>();
        if (userInfoArray.length < 50) {
            TenantSdkResultInfo resultInfo = addUsersAndRelationsBySdk(userInfoArray);
            setReturnUserInfo(result, resultInfo);
            return result.toArray(new TenantSdkUserInfo[]{});
        }

        TenantSdkUserInfo[] userInfoArrayTemp = new TenantSdkUserInfo[50];
        for (int i = 0; i < userInfoArray.length; i++) {
            int offset = i % 50;
            if (i != 0 && offset == 0) {
                TenantSdkResultInfo resultInfo = addUsersAndRelationsBySdk(userInfoArrayTemp);
                setReturnUserInfo(result, resultInfo);
                userInfoArrayTemp = new TenantSdkUserInfo[50];
            }
            userInfoArrayTemp[offset] = userInfoArray[i];
        }

        return result.toArray(new TenantSdkUserInfo[]{});
    }

    @Override
    public void removeUsersFromApps(String[] userIds) throws BusinessException {
        if (userIds == null || userIds.length <= 0) {
            return;
        }

        String sysId = StringUtils.isEmpty(YhtSdkServerProperties.getSysId()) ?
                ApplicationConsts.APPLICATION_ID : YhtSdkServerProperties.getSysId();
        String tenantId = RuntimeEnvironment.getTenantId();

        if (userIds.length < 100) {
            removeUsersBySdk(tenantId, sysId, userIds);
            return;
        }

        String[] userIdArrayTemp = new String[100];
        for (int i = 0; i < userIds.length; i++) {
            int offset = i % 100;
            if (i != 0 && offset == 0) {
                removeUsersBySdk(tenantId, sysId, userIdArrayTemp);
                userIdArrayTemp = new String[100];
            }
            userIdArrayTemp[offset] = userIds[i];
        }

    }

    @Override
    public TenantSdkUserInfo[] addUsers(TenantSdkUserInfo[] userInfoArray) throws BusinessException {
        if (userInfoArray == null || userInfoArray.length <= 0) {
            return null;
        }

        List<TenantSdkUserInfo> result = new ArrayList<>();
        if (userInfoArray.length < 50) {
            TenantSdkResultInfo resultInfo = addUsersBySdk(userInfoArray);
            setReturnUserInfo(result, resultInfo);
            return result.toArray(new TenantSdkUserInfo[]{});
        }

        TenantSdkUserInfo[] userInfoArrayTemp = new TenantSdkUserInfo[50];
        for (int i = 0; i < userInfoArray.length; i++) {
            int offset = i % 50;
            if (i % 49 == 0 && offset == 0) {
                TenantSdkResultInfo resultInfo = addUsersBySdk(userInfoArrayTemp);
                setReturnUserInfo(result, resultInfo);
                userInfoArrayTemp = new TenantSdkUserInfo[50];
            }
            userInfoArrayTemp[offset] = userInfoArray[i];
        }

        return result.toArray(new TenantSdkUserInfo[]{});
    }

    @Override
    public UserSearchResultVO.ContentVO searchUsers(String tenantid, String keyword, int pageNum,
                                                    int pageSize) {
        if (pageNum > CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE) {
            pageNum = CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE;
        }
        //  添加系统id
        String result;
//        if (query.isTenantUserAutoToSystem(tenantid, DeployTypeConfiguration.getSysId())) {
//            result = UserCenter.searchUserList(tenantid, Integer.toString(pageSize),
//                    Integer.toString(pageNum), keyword, "userName");
//        } else {
//            result = UserCenter.searchAppUserList(tenantid, DeployTypeConfiguration.getSysId(), Integer.toString(pageSize),
//                    Integer.toString(pageNum), keyword, "userName");
//        }
        // UserCenter.searchAppUserList方法有问题，故不判断用户是否同步，升级友互通版本时再调整
        result = UserCenter.searchUserList(tenantid, Integer.toString(pageSize),
                Integer.toString(pageNum), keyword, "userName");

        if (StringUtils.isEmpty(result)) {
            return new UserSearchResultVO.ContentVO();
        }
        try {
            UserSearchResultVO resultVO = objectMapper.readValue(result, UserSearchResultVO.class);
            if (resultVO != null && resultVO.getStatus() == 1) {
                return resultVO.getUsers();
            }
        } catch (IOException e) {
            return new UserSearchResultVO.ContentVO();
        }
        return new UserSearchResultVO.ContentVO();

    }

    @Override
    public List<UserSingleQueryVO> isUsersExist(UserInfo[] userInfos) {

        HashMap<String, List<Map<String, String>>> data = new HashMap<>();

        data.put("users", getUserDatas(userInfos));

        String result = com.yonyou.yht.sdk.UserCenter.isUsersExist(JSON.toJSONString(data));

        return getResultInfo(result,userInfos.length);

    }

    @Override
    public List<UserInfo> batchCreateUsers(UserInfo[] userInfos) {

        String sysId = StringUtils.isEmpty(YhtSdkServerProperties.getSysId()) ?
                ApplicationConsts.APPLICATION_ID : YhtSdkServerProperties.getSysId();
        HashMap<String, Object> data = new HashMap<>();

        data.put("users", getUserDatas(userInfos));
        data.put("sysId",sysId);

        String result = UserCenter.addUsers(sysId, JSON.toJSONString(data));

        JSONObject resVo = JSON.parseObject(result);

        JSONArray users = resVo.getJSONArray("users");

        if (users == null) return null;
        List<UserInfo> listUserInfos = JSON.parseArray(users.toJSONString(), UserInfo.class);

        return listUserInfos;
    }

    private  ArrayList<Map<String, String>> getUserDatas(UserInfo[] userInfos){
        ArrayList<Map<String, String>> userDatas = new ArrayList<>();
        for (UserInfo userInfo : userInfos) {

            HashMap<String, String> userData = new HashMap<>();
            userData.put("userMobile", userInfo.getUserMobile());
            userData.put("userName", userInfo.getUserName());
            userData.put("userEmail", userInfo.getUserEmail());
            userDatas.add(userData);
        }
        return userDatas;
    }
    private List<UserSingleQueryVO> getResultInfo(String jsonResult, int size) {
        JSONObject jsonObject = JSON.parseObject(jsonResult);

        ArrayList<UserSingleQueryVO> result = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            UserSingleQueryVO vo = jsonObject.getObject(i + "", UserSingleQueryVO.class);
            result.add(vo);
        }
        return result;
    }

    private TenantSdkResultInfo getResultInfo(String jsonResult) throws BusinessException {
        try {
            TenantSdkResultInfo resultInfo = objectMapper.readValue(jsonResult, TenantSdkResultInfo.class);
            isSucceed(resultInfo);
            if (StringUtils.isNotEmpty(resultInfo.getUsers())) {
                List<TenantSdkUserInfo> userInfos = objectMapper.readValue(resultInfo.getUsers(), new TypeReference<List<TenantSdkUserInfo>>() {
                });
                if (userInfos != null && userInfos.size() > 0) {
                    resultInfo.setUserInfos(userInfos.toArray(new TenantSdkUserInfo[]{}));
                }
            }
            return resultInfo;
        } catch (IOException e) {
            log.error("iuap-tenant-sdk接口返回结果解析失败", e);
            throw new BusinessException("iuap-tenant-sdk接口返回结果解析失败", e.getMessage());
        }
    }

    private void isSucceed(TenantSdkResultInfo resultInfo) throws BusinessException {
        if (TenantSdkResultInfo.STATUS_FAILED.equalsIgnoreCase(resultInfo.getStatus())) {
            StringBuilder errorBuilder = new StringBuilder(resultInfo.getMsg() + ":");
            String[] errorInfoArray = resultInfo.getError();
            if (errorInfoArray != null && errorInfoArray.length > 0) {
                for (String errorInfo : errorInfoArray) {
                    errorBuilder.append(errorInfo).append(" ");
                }
            }
            log.error("iuap-tenant-sdk接口调用失败：" + errorBuilder.toString());
            throw new BusinessException(errorBuilder.toString());

        }
    }

    private void setReturnUserInfo(List<TenantSdkUserInfo> result, TenantSdkResultInfo resultInfo) {
        TenantSdkUserInfo[] userInfoArray = resultInfo.getUserInfos();
        if (userInfoArray != null && userInfoArray.length > 0) {
            result.addAll(Arrays.asList(userInfoArray));
        }
    }

    private TenantSdkResultInfo addUsersBySdk(TenantSdkUserInfo[] userInfoArray) throws BusinessException {
        if (userInfoArray == null || userInfoArray.length <= 0) {
            return null;
        }

        String sysId = StringUtils.isEmpty(YhtSdkServerProperties.getSysId()) ?
                ApplicationConsts.APPLICATION_ID : YhtSdkServerProperties.getSysId();
        String tenantId = RuntimeEnvironment.getTenantId();
        String currentUser = RuntimeEnvironment.getLoginUserId();

        Map<String, Object> addParamMap = new HashMap<>();
        addParamMap.put("users", userInfoArray);
        addParamMap.put("sysId", sysId);

        try {
            String addParamStr = objectMapper.writeValueAsString(addParamMap);
            String result = UserCenter.addUsers(tenantId, sysId, UserSource.LOCAL, currentUser, addParamStr);
            return getResultInfo(result);
        } catch (java.io.IOException e) {
            log.error("添加用户失败：" + e);
            throw new BusinessException("添加用户失败：" + e.getMessage());
        }
    }

    private TenantSdkResultInfo addUsersAndRelationsBySdk(TenantSdkUserInfo[] userInfoArray) throws BusinessException {
        if (userInfoArray == null || userInfoArray.length <= 0) {
            return new TenantSdkResultInfo();
        }

        String sysId = StringUtils.isEmpty(YhtSdkServerProperties.getSysId()) ?
                ApplicationConsts.APPLICATION_ID : YhtSdkServerProperties.getSysId();
        String tenantId = RuntimeEnvironment.getTenantId();
        String currentUser = RuntimeEnvironment.getLoginUserId();

        Map<String, Object> addParamMap = new HashMap<>();
        addParamMap.put("users", userInfoArray);
        addParamMap.put("sysId", sysId);

        try {
            String addParamStr = objectMapper.writeValueAsString(addParamMap);
            String result = UserCenter.addUsersAndRelations(tenantId, sysId, UserSource.LOCAL, currentUser, addParamStr);
            return getResultInfo(result);
        } catch (java.io.IOException e) {
            log.error("添加用户到友工程应用失败：" + e);
            throw new BusinessException("添加用户到友工程应用失败：" + e.getMessage());
        }
    }

    /**
     * 该接口iuap-tenant-sdk-5.0.1-release版本中存在，暂时直接调用，下一版本升级sdk
     *
     * @param tenantId 租户id
     * @param resCode  应用编码
     * @param userIds  （用户的userID集合，最多100）
     */
    private void removeUsersBySdk(String tenantId, String resCode, String[] userIds) throws BusinessException {
        String url = baseUrl + "/tenantrest/removeUsersFromApps/";
        Map<String, Object> jsonStr = new HashMap<>();
        jsonStr.put("tenantId", tenantId);
        jsonStr.put("resCode", resCode);
        jsonStr.put("userIds", userIds);
        String addParamStr;
        try {
            addParamStr = objectMapper.writeValueAsString(jsonStr);
            String result = SignUtils.signAndPost(url, addParamStr);
            getResultInfo(result);
        } catch (JsonProcessingException e) {
            log.error("移除友工程下的用户失败：" + e);
            throw new BusinessException("移除友工程下的用户失败：" + e.getMessage());
        }
    }


}
